#pragma once

#include <vector>
#include <array>
#include <memory>
#include <string>

namespace MiniDB
{

    const size_t PAGE_SIZE = 4096; // 4KB per page

    enum class PageType
    {
        DATA_PAGE,
        INDEX_PAGE,
        META_PAGE
    };

    class Page
    {
    public:
        Page(int page_id, PageType type = PageType::DATA_PAGE);
        ~Page() = default;

        // Page properties
        int getPageId() const { return page_id_; }
        PageType getPageType() const { return page_type_; }
        bool isDirty() const { return is_dirty_; }
        bool isPinned() const { return pin_count_ > 0; }
        size_t getPinCount() const { return pin_count_; }

        // Page operations
        void pin() { pin_count_++; }
        void unpin()
        {
            if (pin_count_ > 0)
                pin_count_--;
        }
        void markDirty() { is_dirty_ = true; }
        void markClean() { is_dirty_ = false; }

        // Data operations
        bool writeData(size_t offset, const void *data, size_t size);
        bool readData(size_t offset, void *buffer, size_t size) const;
        const char* getData() const { return data_.data(); }
        void clear();

        // Utility methods
        size_t getUsedSpace() const { return used_space_; }
        size_t getFreeSpace() const { return PAGE_SIZE - used_space_; }
        bool canFit(size_t size) const { return getFreeSpace() >= size; }

        // Template methods for type-safe operations
        template <typename T>
        bool writeObject(size_t offset, const T &obj)
        {
            return writeData(offset, &obj, sizeof(T));
        }

        template <typename T>
        bool readObject(size_t offset, T &obj) const
        {
            return readData(offset, &obj, sizeof(T));
        }

    private:
        int page_id_;
        PageType page_type_;
        std::array<char, PAGE_SIZE> data_;
        bool is_dirty_;
        size_t pin_count_;
        size_t used_space_;
    };

} // namespace MiniDB
